using System;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Xml;
using System.Drawing;
using System.Xml.Xsl;
using System.Data;
using Microsoft.Win32;
using System.Security.Cryptography;
using System.IO;
using System.Diagnostics;
using System.Net;
using System.Runtime.InteropServices;
using mshtml;
using System.Threading;

namespace Rally_Dekstop
{
    public enum HtmlParserOption {Outter_Html , Inner_Text};
    public class Utilities
    {
        private const string ROOT_REGISTRY_KEY = @"Software\RallyDesk\";
        private static bool isThreadRunning_TestResult = false;
        private static bool isThreadRunning_TestCase = false;
        private static bool isThreadRunning_Defect = false;
        private static bool isThreadRunning_Task = false;
        private static WebBrowser wb = null;

        public Utilities()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        /// <summary>
        /// Encrypts a given string using Rijndael algorithm
        /// </summary>
        /// <param name="clearText"></param>
        /// <param name="Password"></param>
        /// <returns></returns>
        public static string Encrypt(string clearText, string Password)
        {
            // First we need to turn the input string into a byte array. 
            byte[] clearBytes = System.Text.Encoding.Unicode.GetBytes(clearText);


            // Then, we need to turn the password into Key and IV 
            // We are using salt to make it harder to guess our key using a dictionary attack - 
            // trying to guess a password by enumerating all possible words. 
            PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,

            new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });



            // Now get the key/IV and do the encryption using the function that accepts byte arrays. 
            // Using PasswordDeriveBytes object we are first getting 32 bytes for the Key 
            // (the default Rijndael key length is 256bit = 32bytes) and then 16 bytes for the IV. 
            // IV should always be the block size, which is by default 16 bytes (128 bit) for Rijndael. 
            // If you are using DES/TripleDES/RC2 the block size is 8 bytes and so should be the IV size. 
            // You can also read KeySize/BlockSize properties off the algorithm to find out the sizes. 
            byte[] encryptedData = Encrypt(clearBytes, pdb.GetBytes(32), pdb.GetBytes(16));



            // Now we need to turn the resulting byte array into a string. 
            // A common mistake would be to use an Encoding class for that. It does not work 
            // because not all byte values can be represented by characters. 
            // We are going to be using Base64 encoding that is designed exactly for what we are 
            // trying to do. 

            return Convert.ToBase64String(encryptedData);
        }

        private static byte[] Encrypt(byte[] clearData, byte[] Key, byte[] IV)
        {
            // Create a MemoryStream that is going to accept the encrypted bytes 
            MemoryStream ms = new MemoryStream();

            // Create a symmetric algorithm. 
            // We are going to use Rijndael because it is strong and available on all platforms. 
            // You can use other algorithms, to do so substitute the next line with something like 
            //                      TripleDES alg = TripleDES.Create(); 

            Rijndael alg = Rijndael.Create();



            // Now set the key and the IV. 
            // We need the IV (Initialization Vector) because the algorithm is operating in its default 
            // mode called CBC (Cipher Block Chaining). The IV is XORed with the first block (8 byte) 
            // of the data before it is encrypted, and then each encrypted block is XORed with the 
            // following block of plaintext. This is done to make encryption more secure. 
            // There is also a mode called ECB which does not need an IV, but it is much less secure. 
            alg.Key = Key;
            alg.IV = IV;



            // Create a CryptoStream through which we are going to be pumping our data. 
            // CryptoStreamMode.Write means that we are going to be writing data to the stream 
            // and the output will be written in the MemoryStream we have provided. 
            CryptoStream cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write);



            // Write the data and make it do the encryption 
            cs.Write(clearData, 0, clearData.Length);

            // Close the crypto stream (or do FlushFinalBlock). 
            // This will tell it that we have done our encryption and there is no more data coming in, 
            // and it is now a good time to apply the padding and finalize the encryption process. 
            cs.Close();



            // Now get the encrypted data from the MemoryStream. 
            // Some people make a mistake of using GetBuffer() here, which is not the right way. 
            byte[] encryptedData = ms.ToArray();

            return encryptedData;
        }

        private static byte[] Decrypt(byte[] cipherData, byte[] Key, byte[] IV)
        {
            // Create a MemoryStream that is going to accept the decrypted bytes 
            MemoryStream ms = new MemoryStream();

            // Create a symmetric algorithm. 
            // We are going to use Rijndael because it is strong and available on all platforms. 
            // You can use other algorithms, to do so substitute the next line with something like 
            //TripleDES alg = TripleDES.Create(); 
            Rijndael alg = Rijndael.Create();

            // Now set the key and the IV. 
            // We need the IV (Initialization Vector) because the algorithm is operating in its default 
            // mode called CBC (Cipher Block Chaining). The IV is XORed with the first block (8 byte) 
            // of the data after it is decrypted, and then each decrypted block is XORed with the previous 
            // cipher block. This is done to make encryption more secure. 
            // There is also a mode called ECB which does not need an IV, but it is much less secure. 
            alg.Key = Key;
            alg.IV = IV;

            // Create a CryptoStream through which we are going to be pumping our data. 
            // CryptoStreamMode.Write means that we are going to be writing data to the stream 
            // and the output will be written in the MemoryStream we have provided. 
            CryptoStream cs = new CryptoStream(ms, alg.CreateDecryptor(), CryptoStreamMode.Write);

            // Write the data and make it do the decryption 
            cs.Write(cipherData, 0, cipherData.Length);

            // Close the crypto stream (or do FlushFinalBlock). 
            // This will tell it that we have done our decryption and there is no more data coming in, 
            // and it is now a good time to remove the padding and finalize the decryption process. 
            cs.Close();



            // Now get the decrypted data from the MemoryStream. 
            // Some people make a mistake of using GetBuffer() here, which is not the right way. 
            byte[] decryptedData = ms.ToArray();

            return decryptedData;

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="cipherText"></param>
        /// <param name="Password"></param>
        /// <returns></returns>
        public static string Decrypt(string cipherText, string Password)
        {
            // First we need to turn the input string into a byte array. 
            // We presume that Base64 encoding was used 
            byte[] cipherBytes = Convert.FromBase64String(cipherText);

            // Then, we need to turn the password into Key and IV 
            // We are using salt to make it harder to guess our key using a dictionary attack - 
            // trying to guess a password by enumerating all possible words. 
            PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,

            new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });

            // Now get the key/IV and do the decryption using the function that accepts byte arrays. 
            // Using PasswordDeriveBytes object we are first getting 32 bytes for the Key 
            // (the default Rijndael key length is 256bit = 32bytes) and then 16 bytes for the IV. 
            // IV should always be the block size, which is by default 16 bytes (128 bit) for Rijndael. 
            // If you are using DES/TripleDES/RC2 the block size is 8 bytes and so should be the IV size. 
            // You can also read KeySize/BlockSize properties off the algorithm to find out the sizes. 
            byte[] decryptedData = Decrypt(cipherBytes, pdb.GetBytes(32), pdb.GetBytes(16));


            // Now we need to turn the resulting byte array into a string. 
            // A common mistake would be to use an Encoding class for that. It does not work 
            // because not all byte values can be represented by characters. 
            // We are going to be using Base64 encoding that is designed exactly for what we are 
            // trying to do. 

            return System.Text.Encoding.Unicode.GetString(decryptedData);
        }

        public static void WriteRegistryKeyValue(string superKeyName, string keyName, string keyValue)
        {

            // Opening the registry key
            RegistryKey rootKey = Registry.CurrentUser;

            // Open a subKey as read-only
            RegistryKey subKey = rootKey.CreateSubKey(ROOT_REGISTRY_KEY + superKeyName);

            subKey.SetValue(keyName, keyValue);

            subKey.Close();

        }


        public static Hashtable ReadRegistryKeyValues(string keyName)
        {
            Hashtable result = new Hashtable();

            RegistryKey subKey = Registry.CurrentUser.OpenSubKey(ROOT_REGISTRY_KEY + keyName);

            if (subKey != null)
            {

                string[] valueNames = subKey.GetValueNames();

                foreach (string strName in valueNames)
                {
                    string strValue = (string)subKey.GetValue(strName);

                    result.Add(strName, strValue);
                }
            }

            return result;
        }

        public static void WriteRegistryKeyValues(string keyName, Hashtable values, bool clearBeforeWriting)
        {
            RegistryKey subKey = Registry.CurrentUser.CreateSubKey(ROOT_REGISTRY_KEY + keyName);

            if (clearBeforeWriting)
            {
                string[] strNames = subKey.GetValueNames();

                foreach (string strName in strNames)
                {
                    subKey.DeleteValue(strName);
                }
            }

            foreach (string strName in values.Keys)
            {
                subKey.SetValue(strName, (string)values[strName]);
            }

            subKey.Close();
        }

        public static void ClearAll(Control parentCtrl)
        {
            foreach (Control ctrl in parentCtrl.Controls)
            {
                try
                {
                    if (ctrl is TextBox)
                    {
                        ctrl.Text = string.Empty;
                    }
                    else if (ctrl is ComboBox)
                    {
                        ((ComboBox)ctrl).SelectedIndex = -1;
                    }
                    else if (ctrl is ListView)
                    {
                        ((ListView)ctrl).Items.Clear();
                    }
                    else if (ctrl is Panel)
                    {
                        ClearAll(ctrl);
                    }
                    else if (ctrl is CheckBox)
                    {
                        ((CheckBox)ctrl).Checked = false;
                    }

                }
                catch (Exception)
                {
                }
            }
        }

        public static string ReadRegistryKeyValue(string superKeyName, string keyName)
        {

            // Opening the registry key
            RegistryKey rootKey = Registry.CurrentUser;
            // Open a subKey as read-only
            RegistryKey subKey = rootKey.OpenSubKey(ROOT_REGISTRY_KEY + superKeyName);

            // If the RegistrySubKey doesn't exist -> (null)
            if (subKey == null)
            {
                return string.Empty;
            }
            else
            {
                try
                {
                    object val = subKey.GetValue(keyName);
                    if (val == null)
                    {
                        throw new System.NullReferenceException();
                    }

                    return (string)val;
                }
                catch (Exception)
                {
                    return string.Empty;
                }
            }

        }

        public static void GetWorkspaceSpecifics(string type)
        {
            Thread toRunService = null;
            string key = RallyDesk.CacheKey + RallyDesk.CURRENTWORKSPACE.SelectedWorkSpaceRef + type;
            switch (type)
            {
                case "TestResult": { toRunService = new Thread(new ThreadStart(GetWorkspaceSpecifics_TestResult));
                                    if (isThreadRunning_TestResult)
                                        return;
                                        break;
                                   }
                case "TestCase":   {
                                       toRunService = new Thread(new ThreadStart(GetWorkspaceSpecifics_TestCase));
                                       if (isThreadRunning_TestCase)
                                         return;                   
                    break;
                                   }
                case "Defect":     {
                                       toRunService = new Thread(new ThreadStart(GetWorkspaceSpecifics_Defect));
                                       if (isThreadRunning_Defect)
                                           return;                   
                    break;
                                   }
                case "Task":      {
                                       toRunService = new Thread(new ThreadStart(GetWorkspaceSpecifics_Task));
                                       if (isThreadRunning_Task)
                                           return;                  
                    break;
                                   }
                      
            }

            


            if(!RallyDesk.Cache.Contains(key))
            {
                toRunService.Start();

                Rally_Dekstop.Program.RallyMain.toolStripStatusLabel.Text = "Getting " + type + " Specifics...";
                Rally_Dekstop.Program.RallyMain.ProgressBarMain.Style = ProgressBarStyle.Marquee;
                Rally_Dekstop.Program.RallyMain.ProgressBarMain.Visible = true;

                while (toRunService.IsAlive)
                {
                    Application.DoEvents();
                }
                toRunService.Abort();
                Rally_Dekstop.Program.RallyMain.ProgressBarMain.Visible = false;
                Rally_Dekstop.Program.RallyMain.toolStripStatusLabel.Text = "Ready";
            }
        }

        private static void GetWorkspaceSpecifics_TestResult()
        {
            isThreadRunning_TestResult = true;
            try
            {
                if (RallyDesk.CURRENTWORKSPACE.WorkSpaceSpecifics.TestResult.Verdicts.Count <= 0)
                {
                    string key = RallyDesk.CacheKey + RallyDesk.CURRENTWORKSPACE.SelectedWorkSpaceRef + "TestResult";

                    IRallyService service = null;
                    if (RallyDesk.CURRENTWORKSPACE.SelectedWorkSpaceType == "UseCase")
                    {
                        service = new RallyAPIUseCase(RallyDesk.url);
                    }
                    else
                    {
                        service = new RallyAPIUserStory(RallyDesk.url);
                    }

                    if (!RallyDesk.Cache.Contains(key))
                    {
                        RallyDesk.CURRENTWORKSPACE.WorkSpaceSpecifics.TestResult.Verdicts = service.GetTestVerdicts(RallyDesk.CURRENTWORKSPACE.SelectedWorkSpaceRef);
                        RallyDesk.Cache.Add(key, RallyDesk.CURRENTWORKSPACE.WorkSpaceSpecifics.TestResult.Verdicts);
                    }
                    else
                        RallyDesk.CURRENTWORKSPACE.WorkSpaceSpecifics.TestResult.Verdicts = (ArrayList)RallyDesk.Cache.Get(key);
                }
            }
            finally
            {
                isThreadRunning_TestResult = false;
            
            }
        }
        private static void GetWorkspaceSpecifics_TestCase()
        {
            isThreadRunning_TestCase = true;
            try
            {
                if (RallyDesk.CURRENTWORKSPACE.WorkSpaceSpecifics.TestCase.Method.Count <= 0)
                {
                    string key = RallyDesk.CacheKey + RallyDesk.CURRENTWORKSPACE.SelectedWorkSpaceRef + "TestCase";

                    IRallyService service = null;
                    if (RallyDesk.CURRENTWORKSPACE.SelectedWorkSpaceType == "UseCase")
                    {
                        service = new RallyAPIUseCase(RallyDesk.url);
                    }
                    else
                    {
                        service = new RallyAPIUserStory(RallyDesk.url);
                    }

                    if (!RallyDesk.Cache.Contains(key))
                    {
                        RallyDesk.CURRENTWORKSPACE.WorkSpaceSpecifics.TestCase = service.GetTestCaseSpecifics(RallyDesk.CURRENTWORKSPACE.SelectedWorkSpaceRef);
                        RallyDesk.Cache.Add(key, RallyDesk.CURRENTWORKSPACE.WorkSpaceSpecifics.TestCase);
                    }
                    else
                        RallyDesk.CURRENTWORKSPACE.WorkSpaceSpecifics.TestCase = (TestCaseSpecifics)RallyDesk.Cache.Get(key);

                }
            }
            finally
            {
                isThreadRunning_TestCase = false;
            }
        }
        private static void GetWorkspaceSpecifics_Defect()
        {
            isThreadRunning_Defect = true;
            try
            {

                if (RallyDesk.CURRENTWORKSPACE.WorkSpaceSpecifics.Defect.Priorities.Count <= 0)
                {
                    string key = RallyDesk.CacheKey + RallyDesk.CURRENTWORKSPACE.SelectedWorkSpaceRef + "Defect";

                    IRallyService service = null;
                    if (RallyDesk.CURRENTWORKSPACE.SelectedWorkSpaceType == "UseCase")
                    {
                        service = new RallyAPIUseCase(RallyDesk.url);
                    }
                    else
                    {
                        service = new RallyAPIUserStory(RallyDesk.url);
                    }
                    if (!RallyDesk.Cache.Contains(key))
                    {
                        RallyDesk.CURRENTWORKSPACE.WorkSpaceSpecifics.Defect = service.GetDefectSpecifics(RallyDesk.CURRENTWORKSPACE.SelectedWorkSpaceRef);
                        RallyDesk.Cache.Add(key, RallyDesk.CURRENTWORKSPACE.WorkSpaceSpecifics.Defect);
                    }
                    else
                        RallyDesk.CURRENTWORKSPACE.WorkSpaceSpecifics.Defect = (DefectSpecifics)RallyDesk.Cache.Get(key);

                }
            }
            finally 
            {
                isThreadRunning_Defect = false;
            }
        }
        private static void GetWorkspaceSpecifics_Task()
        {
            isThreadRunning_Task = true;
            try
            {
                if (RallyDesk.CURRENTWORKSPACE.WorkSpaceSpecifics.Task.States.Count <= 0)
                {
                    string key = RallyDesk.CacheKey + RallyDesk.CURRENTWORKSPACE.SelectedWorkSpaceRef + "Task";

                    IRallyService service = null;
                    if (RallyDesk.CURRENTWORKSPACE.SelectedWorkSpaceType == "UseCase")
                    {
                        service = new RallyAPIUseCase(RallyDesk.url);
                    }
                    else
                    {
                        service = new RallyAPIUserStory(RallyDesk.url);
                    }
                    if (!RallyDesk.Cache.Contains(key))
                    {
                        RallyDesk.CURRENTWORKSPACE.WorkSpaceSpecifics.Task = service.GetTaskSpecifics(RallyDesk.CURRENTWORKSPACE.SelectedWorkSpaceRef);
                        RallyDesk.Cache.Add(key, RallyDesk.CURRENTWORKSPACE.WorkSpaceSpecifics.Task);
                    }
                    else
                        RallyDesk.CURRENTWORKSPACE.WorkSpaceSpecifics.Task = (TaskSpecifics)RallyDesk.Cache.Get(key);

                }
            }
            finally
            {
                isThreadRunning_Task = false;
            }
        }





        public static void SelectWork(string work, int index)
        {
            try
            {
                Rally_Dekstop.Program.RallyMain.Enabled = false;
                if (!(RallyDesk.CURRENTWORKSPACE.SelectedWorkSpace.Equals(string.Empty)))
                {
                    RallyDesk.CURRENTWORKSPACE = null;
                    RallyDesk.CURRENTWORKSPACE = new WorkSpace();
                }
                Rally_Dekstop.Program.RallyMain.toolStripStatusLabel.Text = "Getting Workspace type...";
                RallyDesk.CURRENTWORKSPACE.SelectedWorkSpace = work;
                RallyDesk.CURRENTWORKSPACE.SelectedWorkSpaceRef = ((string)RallyDesk.WORKSPACEREFERENCES[index]);

                if (!RallyDesk.Cache.Contains(RallyDesk.CacheKey + RallyDesk.CURRENTWORKSPACE.SelectedWorkSpaceRef))
                {
                    Thread toRunService = null;
                    toRunService = new Thread(new ThreadStart(SelectWorkOnThread));

                    toRunService.Start();
                    Rally_Dekstop.Program.RallyMain.toolStripStatusLabel.Text = "Getting Projects...";
                    Rally_Dekstop.Program.RallyMain.ProgressBarMain.Style = ProgressBarStyle.Marquee;
                    Rally_Dekstop.Program.RallyMain.ProgressBarMain.Visible = true;

                    while (toRunService.IsAlive)
                    {

                        Application.DoEvents();
                    }
                    toRunService.Abort();
                    Rally_Dekstop.Program.RallyMain.ProgressBarMain.Visible = false;
                    Rally_Dekstop.Program.RallyMain.toolStripStatusLabel.Text = "Ready";

                    //this.GetWorkspaceSpecifics();
                    RallyDesk.Cache.Add(RallyDesk.CacheKey + RallyDesk.CURRENTWORKSPACE.SelectedWorkSpaceRef, RallyDesk.CURRENTWORKSPACE);

                }
                else
                {
                    RallyDesk.CURRENTWORKSPACE = (WorkSpace)RallyDesk.Cache.Get(RallyDesk.CacheKey + RallyDesk.CURRENTWORKSPACE.SelectedWorkSpaceRef);

                }

            }
            finally
            {
                Rally_Dekstop.Program.RallyMain.Enabled = true;
            }
        }
        private static void SelectWorkOnThread()
        {
            IRallyService service = new RallyAPIUseCase(RallyDesk.url);
            object[] details = new object[2];
            details = service.GetWorkspaceType_Projects(RallyDesk.CURRENTWORKSPACE.SelectedWorkSpaceRef);
            RallyDesk.CURRENTWORKSPACE.SelectedWorkSpaceType = details[0] as string;//service.GetWorkspaceType(RallyDesk.CURRENTWORKSPACE.SelectedWorkSpaceRef);
            RallyDesk.CURRENTWORKSPACE.Projects = details[1] as Projects;
        }



        public static void SetProjects()
        {
            if (Rally_Dekstop.Program.RallyMain.cmb_projects.Items.Count > 0)
                Rally_Dekstop.Program.RallyMain.cmb_projects.Items.Clear();
            foreach (string proj in RallyDesk.CURRENTWORKSPACE.Projects.Project)
                Rally_Dekstop.Program.RallyMain.cmb_projects.Items.Add(proj);

            Rally_Dekstop.Program.RallyMain.cmb_projects.SelectedIndex = 0;
            RallyDesk.CURRENTWORKSPACE.SelectedProject = Rally_Dekstop.Program.RallyMain.cmb_projects.Text;
            RallyDesk.CURRENTWORKSPACE.SelectedProjectRef = ((string)RallyDesk.CURRENTWORKSPACE.Projects.ProjectRef[Rally_Dekstop.Program.RallyMain.cmb_projects.SelectedIndex]);
            
        }
        public static string GetTempFilePath()
        {
            return Path.GetTempFileName();
        }

        public static void ClearAllRallyDeskInfo()
        {
            RallyDesk.Username = null;
            RallyDesk.CacheKey = null;
            RallyDesk.Password = null;
            RallyDesk.HOSTNAME = null;
            RallyDesk.CURRENTWORKSPACE = null;
            RallyDesk.WORKSPACENAMES.Clear();
            RallyDesk.WORKSPACEREFERENCES.Clear();
            Rally_Dekstop.Program.RallyMain.cmb_projects.Items.Clear();            
        }

        public static string CovertToRallyTimeStamp(System.DateTime DT)
        {
            
            StringBuilder ST = new StringBuilder();
            string result;
            ST.Append(Convert.ToString(DT.Year));
            ST.Append("-");
            ST.Append(Convert.ToString(DT.Month));
            ST.Append("-");
            ST.Append(Convert.ToString(DT.Day));
            ST.Append("T");
            ///ST.Append(Convert.ToString(DT.TimeOfDay.Hours));
            ST.Append("00");
            ST.Append(":");
            //ST.Append(Convert.ToString(DT.TimeOfDay.Minutes));
            ST.Append("00");
            ST.Append(":");
            ST.Append("00");
           // ST.Append(Convert.ToString(DT.TimeOfDay.Seconds));
            ST.Append(".000Z");
            result = ST.ToString();

            return result;
        }
        public static string CovertToRallyTimeStamp(string Year, string Month, string Day)
        {
            StringBuilder ST = new StringBuilder();
            string result;
            ST.Append(Year);
            ST.Append("-");
            ST.Append(Month);
            ST.Append("-");
            ST.Append(Day);
            ST.Append("T");
            ///ST.Append(Convert.ToString(DT.TimeOfDay.Hours));
            ST.Append("00");
            ST.Append(":");
            //ST.Append(Convert.ToString(DT.TimeOfDay.Minutes));
            ST.Append("00");
            ST.Append(":");
            ST.Append("00");
            // ST.Append(Convert.ToString(DT.TimeOfDay.Seconds));
            ST.Append(".000Z");
            result = ST.ToString();

            return result;
        }

        public static string ParseHTMLTextToRallyFormat(string source)
        {

                try
                {

                    string result;

                    // Remove HTML Development formatting

                    // Replace line breaks with space

                    // because browsers inserts space

                    result = source.Replace("\r", " ");
                    // Replace line breaks with space

                    // because browsers inserts space

                    result = result.Replace("\n", " ");
                    // Remove step-formatting

                    result = result.Replace("\t", string.Empty);
                    // Remove repeating speces becuase browsers ignore them

                    result = System.Text.RegularExpressions.Regex.Replace(result, 
                                                                          @"( )+", " ");

                    // Remove the header (prepare first by clearing attributes)

                    result = System.Text.RegularExpressions.Regex.Replace(result, 
                             @"<( )*head([^>])*>","<head>", 
                             System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                    result = System.Text.RegularExpressions.Regex.Replace(result, 
                             @"(<( )*(/)( )*head( )*>)","</head>", 
                             System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                    result = System.Text.RegularExpressions.Regex.Replace(result, 
                             "(<head>).*(</head>)",string.Empty, 
                             System.Text.RegularExpressions.RegexOptions.IgnoreCase);

                   

                    return result;

                }
                catch
                {
                    MessageBox.Show("Error");
                    return source;
                }

        }

        /// <summary>
        /// This method prints any document by using the "Print" shell command.
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static string PrintDocument(string filePath)
        {
            string result = string.Empty;

            try
            {

                Process printJob = new Process();
                printJob.StartInfo.FileName = filePath;
                printJob.StartInfo.UseShellExecute = true;
                printJob.StartInfo.Verb = "print";
                printJob.Start();
            }

            catch (System.ComponentModel.Win32Exception ex)
            {
                result = ex.Message;
            }

            return result;
        }

        public static string HtmlParser(string tagName, string htmlText, HtmlParserOption opt)
        {
            string toreturn = string.Empty;
            if(wb == null)
            wb = new WebBrowser();

            string tempFilename = System.IO.Path.GetTempFileName();
            if (System.IO.File.Exists(tempFilename))
            {
                try
                {
                    System.IO.File.Delete(tempFilename);
                }
                catch (IOException)
                { }
            }

            System.IO.File.WriteAllText(tempFilename + ".html", htmlText,Encoding.UTF8);

            wb.Navigate(tempFilename + ".html");
            System.Windows.Forms.Application.DoEvents();

            //toretrun = wb.Document.Body.InnerHtml;

            foreach (HtmlElement ele in wb.Document.All)
            {
                if (string.Compare(ele.TagName, tagName, true)== 0)
                {
                    switch(opt)
                    {
                        case HtmlParserOption.Outter_Html:
                                toreturn = ele.OuterHtml.Trim();
                                break;
                        case HtmlParserOption.Inner_Text:
                            toreturn = ele.InnerText.Trim().Replace(Environment.NewLine, "\n");
                                break;

                    }
                }
            }

            try
            {
                System.IO.File.Delete(tempFilename + ".html");
            }
            catch (IOException)
            { }
            return toreturn;
        }
    
    }
}
